package com.genreate.util.youdao;

import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.genreate.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Slf4j
public class YouDaoV3Api {

    private static final String YOUDAO_URL = "https://openapi.youdao.com/api";
    //您的应用ID
    private static final String APP_KEY = "4d463e990a215fc9";
    //您的应用密钥
    private static final String APP_SECRET = "TwU2tMHh63ISgtPNIu8YvNIYVvVwxgjF";

    public static void main(String[] args) {
        getEnum("标配,OTA将推送,无,选装");
    }

    /**
     * 获取枚举
     *
     * @param str str
     */
    public static void getEnum(String str) {
        getEnum(Arrays.asList(str.split(",")));
    }

    /**
     * 获取枚举
     *
     * @param strs 字符串
     * @return {@link String }
     */
    public static void getEnum(List<String> strs) {
        if (IterUtil.isEmpty(strs)) {
            return;
        }
        StringBuilder builder = StrUtil.builder("");
        for (int i = 0; i < strs.size(); i++) {
            String notStr = strs.get(i);
            builder.append(StrUtil.format("{}({}, \"{}\"),\n", zhToEnFormat(notStr), (i + 1), notStr));
        }
        StringUtils.setClipboard(builder);
    }

    /**
     * 中文转英语 格式化
     *
     * @param text 文本
     * @return {@link String }
     */
    public static String zhToEnFormat(String text) {
        text = zhToEn(text);
        return text.replaceAll(" ", "_").toUpperCase();
    }

    /**
     * 中文转英语
     *
     * @param text 文本
     * @return {@link String }
     */
    public static String zhToEn(String text) {
        return translateMsg(text, LanguageTypeEnum.ZH.getCode(), LanguageTypeEnum.EN.getCode());
    }

    /**
     * 有道云翻译api
     * 错误时返回空
     *
     * @param allText        需要翻译的文本
     * @param sourceLanguage 源语言属于哪国语言
     * @param targetLanguage 目标语言属于哪国语言
     */
    public static String translateMsg(String allText, String sourceLanguage, String targetLanguage) {
        try {
            if (sourceLanguage.equals(targetLanguage)) {
                // 语言类型一样时不调用翻译
                return allText;
            }
            return translate(allText, sourceLanguage, targetLanguage);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }

    /**
     * 有道云翻译api
     *
     * @param allText        需要翻译的文本
     * @param sourceLanguage 源语言属于哪国语言
     * @param targetLanguage 目标语言属于哪国语言
     * @throws IOException 抛出的异常
     */
    public static String translate(String allText, String sourceLanguage, String targetLanguage) throws Exception {
        StringBuilder allResultBuilder = new StringBuilder();
        if (allText.length() >= 5000) {
            //报错,因为超过5000之后我没法短词,比如一个英文单词,在正中间被5000断开了,就没法翻译了
            log.error("有道翻译一次最多翻译5000个字符,当前传来的字符有:{}个,超出范围了", allText.length());
            throw new Exception(StrUtil.format("有道翻译一次最多翻译5000个字符,当前传来的字符有:{}个,超出范围了", allText.length()));
        }
        return onceTranslate(allText, sourceLanguage, targetLanguage);
    }

    public static String onceTranslate(String allText, String sourceLanguage, String targetLanguage) throws Exception {
        Map<String, String> params = new HashMap<String, String>();
        String salt = String.valueOf(System.currentTimeMillis());
        params.put("from", sourceLanguage);
        params.put("to", targetLanguage);
        params.put("signType", "v3");
        String curtime = String.valueOf(System.currentTimeMillis() / 1000);
        params.put("curtime", curtime);
        String signStr = APP_KEY + truncate(allText) + salt + curtime + APP_SECRET;
        String sign = getDigest(signStr);
        params.put("appKey", APP_KEY);
        params.put("q", allText);
        params.put("salt", salt);
        params.put("sign", sign);
        /** 处理结果 */
        return requestForHttp(YOUDAO_URL, params);
    }

    public static String requestForHttp(String url, Map<String, String> params) throws Exception {
        String json = null;
        String translation;
        /** 创建HttpClient */
        CloseableHttpClient httpClient = HttpClients.createDefault();

        /** httpPost */
        HttpPost httpPost = new HttpPost(url);
        List<NameValuePair> paramsList = new ArrayList<NameValuePair>();
        Iterator<Map.Entry<String, String>> it = params.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, String> en = it.next();
            String key = en.getKey();
            String value = en.getValue();
            paramsList.add(new BasicNameValuePair(key, value));
        }
        httpPost.setEntity(new UrlEncodedFormEntity(paramsList, "UTF-8"));
        try (CloseableHttpResponse httpResponse = httpClient.execute(httpPost);) {
            Header[] contentType = httpResponse.getHeaders("Content-Type");
            log.info("Content-Type:" + contentType[0].getValue());
            /** 响应不是音频流，直接显示结果 */
            HttpEntity httpEntity = httpResponse.getEntity();
            json = EntityUtils.toString(httpEntity, "UTF-8");
            EntityUtils.consume(httpEntity);
            log.info(json);
            translation = JSONUtil.parseObj(json).getJSONArray("translation").get(0).toString();
        } catch (Exception ex) {
            throw new Exception("翻译出现错误");
        }
        if (StrUtil.isEmpty(translation)) {
            throw new Exception("翻译出现错误");
        }
        return translation;
    }

    /**
     * 生成加密字段
     */
    public static String getDigest(String string) {
        if (string == null) {
            return null;
        }
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        byte[] btInput = string.getBytes(StandardCharsets.UTF_8);
        try {
            MessageDigest mdInst = MessageDigest.getInstance("SHA-256");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (NoSuchAlgorithmException e) {
            return null;
        }
    }

    /**
     * @param result 音频字节流
     * @param file   存储路径
     */
    private static void byte2File(byte[] result, String file) {
        File audioFile = new File(file);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(audioFile);
            fos.write(result);

        } catch (Exception e) {
            log.info(e.toString());
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public static String truncate(String q) {
        if (q == null) {
            return null;
        }
        int len = q.length();
        String result;
        return len <= 20 ? q : (q.substring(0, 10) + len + q.substring(len - 10, len));
    }
}
